package service

import (
	"context"
	"fmt"
	"math/rand"
	"strconv"
	"takeout-grpc/basic/config"
	__ "takeout-grpc/basic/proto"
	"takeout-grpc/handler/model"
	"time"

	"github.com/google/uuid"
)

type Server struct {
	__.UnimplementedTakeoutServer
}

func (s *Server) OrderAdd(_ context.Context, in *__.OrderAddReq) (*__.OrderAddResp, error) {
	//校验用户Id
	var user model.User
	err := config.DB.First(&user, in.UserId).Error
	if err != nil {
		return nil, fmt.Errorf("用户id不存在:%v", err)
	}
	//校验商家Id
	var merchant model.Merchant
	err = config.DB.First(&merchant, in.MerchantId).Error
	if err != nil {
		return nil, fmt.Errorf("商家id不存在:%v", err)
	}
	//校验商品ID
	var shop model.Shop
	err = config.DB.First(&shop, in.ShopId).Error
	if err != nil {
		return nil, fmt.Errorf("商品id不存在:%v", err)
	}
	//骑手ID
	var rider model.Rider
	err = config.DB.First(&rider, in.RiderId).Error
	if err != nil {
		return nil, fmt.Errorf("骑手id不存在:%v", err)
	}
	//生成订单号
	orderSn := fmt.Sprintf("order:%s", uuid.NewString())
	//创建订单
	order := model.Order{
		MerchantId: uint(in.MerchantId),
		UserId:     uint(in.UserId),
		ShopId:     uint(in.ShopId),
		RiderId:    uint(in.RiderId),
		OrderSn:    orderSn,
		Address:    in.Address,
		Stock:      int(in.Stock),
		Total:      shop.Price * float64(in.Stock),
		Status:     int(in.Status),
	}
	err = config.DB.Create(&order).Error
	if err != nil {
		return nil, fmt.Errorf("订单创建失败")
	}
	//扣减库存
	config.DB.Model(&model.Shop{}).Updates(strconv.Itoa(shop.Num - int(in.Stock)))
	//存入 Redis，设置 10 分钟过期时间，防止缓存穿透
	orderKey := fmt.Sprintf("order:%d", order.ID)
	config.Rdb.Set(config.Ctx, orderKey, order.ID, time.Minute*10)
	return &__.OrderAddResp{
		OrderId: int64(order.ID),
		OrderSn: orderSn,
	}, nil
}

// MerchantList 商家查看订单列表
func (s *Server) MerchantList(_ context.Context, in *__.MerchantListReq) (*__.MerchantListResp, error) {
	//分页参数
	offest := (in.Page - 1) * in.Size
	//校验商家Id
	var merchant model.Merchant
	err := config.DB.First(&merchant, in.MerchantId).Error
	if err != nil {
		return nil, fmt.Errorf("商家id不存在")
	}
	//查询数据库
	var orders []model.Order
	err = config.DB.Offset(int(offest)).Limit(int(in.Size)).Where("merchant_id=?", in.MerchantId).Find(&orders).Error
	if err != nil {
		return nil, fmt.Errorf("查询数据库失败%v", err)
	}
	//转换格式
	var orderList []*__.OrderInto
	for _, o := range orders {
		orderList = append(orderList, &__.OrderInto{
			MerchantId: uint64(o.MerchantId),
			UserId:     uint64(o.UserId),
			ShopId:     uint64(o.ShopId),
			RiderId:    uint64(o.RiderId),
			Address:    o.Address,
			Stock:      int64(o.Stock),
			Status:     int64(o.Status),
			OrderSn:    o.OrderSn,
		})
	}
	return &__.MerchantListResp{
		List: orderList,
	}, nil
}

// RiderList 骑手查看订单列表
func (s *Server) RiderList(_ context.Context, in *__.RiderListReq) (*__.RiderListResp, error) {
	//分页参数
	offest := (in.Page - 1) * in.Size
	//校验骑手Id
	var rider model.Rider
	err := config.DB.First(&rider, in.RiderId).Error
	if err != nil {
		return nil, fmt.Errorf("骑手id不存在")
	}
	//查询数据库
	var orders []model.Order
	err = config.DB.Offset(int(offest)).Limit(int(in.Size)).Where("rider_id=?", in.RiderId).Find(&orders).Error
	if err != nil {
		return nil, fmt.Errorf("查询数据库失败%v", err)
	}
	//转换格式
	var orderList []*__.OrderInto
	for _, o := range orders {
		orderList = append(orderList, &__.OrderInto{
			MerchantId: uint64(o.MerchantId),
			UserId:     uint64(o.UserId),
			ShopId:     uint64(o.ShopId),
			RiderId:    uint64(o.RiderId),
			Address:    o.Address,
			Stock:      int64(o.Stock),
			Status:     int64(o.Status),
			OrderSn:    o.OrderSn,
		})
	}
	return &__.RiderListResp{
		List: orderList,
	}, nil
}

// MerchantFind 商家查看订单状态
func (s *Server) MerchantFind(_ context.Context, in *__.MerchantFindReq) (*__.MerchantFindResp, error) {
	//校验商家Id
	var merchant model.Merchant
	err := config.DB.First(&merchant, in.MerchantId).Error
	if err != nil {
		return nil, fmt.Errorf("商家id不存在")
	}
	//查询数据库
	var orders []model.Order
	err = config.DB.Where("merchant_id=?", in.MerchantId).Find(&orders).Error
	if err != nil {
		return nil, fmt.Errorf("查询数据库失败%v", err)
	}
	//转换格式
	var orderList []*__.OrderInto
	for _, o := range orders {
		orderList = append(orderList, &__.OrderInto{
			MerchantId: uint64(o.MerchantId),
			UserId:     uint64(o.UserId),
			ShopId:     uint64(o.ShopId),
			RiderId:    uint64(o.RiderId),
			Address:    o.Address,
			Stock:      int64(o.Stock),
			Status:     int64(o.Status),
			OrderSn:    o.OrderSn,
		})
	}
	return &__.MerchantFindResp{
		List: orderList,
	}, nil
}

// UserFind 用户查看订单状态
func (s *Server) UserFind(_ context.Context, in *__.UserFindReq) (*__.UserFindResp, error) {
	//校验商家Id
	var user model.User
	err := config.DB.First(&user, in.UserId).Error
	if err != nil {
		return nil, fmt.Errorf("用户id不存在")
	}
	//查询数据库
	var orders []model.Order
	err = config.DB.Where("user_id=?", in.UserId).Find(&orders).Error
	if err != nil {
		return nil, fmt.Errorf("查询数据库失败%v", err)
	}
	//转换格式
	var orderList []*__.OrderInto
	for _, o := range orders {
		orderList = append(orderList, &__.OrderInto{
			MerchantId: uint64(o.MerchantId),
			UserId:     uint64(o.UserId),
			ShopId:     uint64(o.ShopId),
			RiderId:    uint64(o.RiderId),
			Address:    o.Address,
			Stock:      int64(o.Stock),
			Status:     int64(o.Status),
			OrderSn:    o.OrderSn,
		})
	}
	return &__.UserFindResp{
		List: orderList,
	}, nil
}

// RiderAuction 骑手配送排行榜
func (s *Server) RiderAuction(_ context.Context, in *__.RiderAuctionReq) (*__.RiderAuctionResp, error) {

	//查询数据库
	var riders []model.Rider
	db := config.DB.Find(&riders)
	//骑手接单量排序
	if in.Accept == 1 {
		db = db.Order("accept desc")
	}
	//转换格式
	var riderList []*__.RiderInto
	for _, o := range riders {
		riderList = append(riderList, &__.RiderInto{
			Name:   o.Name,
			Phone:  o.Phone,
			Accept: int64(o.Accept),
		})
	}
	return &__.RiderAuctionResp{
		List: riderList,
	}, nil
}

// Merchant 商家门店展示功能
func (s *Server) Merchant(_ context.Context, in *__.MerchantReq) (*__.MerchantResp, error) {
	//分页参数
	offest := (in.Page - 1) * in.Size
	//查询数据库
	var merchants []model.Merchant
	db := config.DB.Offset(int(offest)).Limit(int(in.Size))

	//关键词搜索
	if in.Cate != "" {
		db = db.Where("cate like ?", in.Cate)
	}

	//按“评分”排序
	if in.Rating == 0 {
		db = db.Order("rating desc")
	}
	if in.Rating == 1 {
		db = db.Order("rating asc")
	}

	db.Find(&merchants)

	//转换格式
	var merchantList []*__.MerchantInto
	for _, o := range merchants {
		merchantList = append(merchantList, &__.MerchantInto{
			MerchantId: uint64(o.ID),
			Name:       o.Name,
			Phone:      o.Phone,
			Cate:       o.Cate,
			Address:    o.Address,
			Rating:     float32(o.Rating),
		})
	}
	return &__.MerchantResp{
		List: merchantList,
	}, nil
}

// CreateAppoint 消费者预约功能
func (s *Server) CreateAppoint(_ context.Context, in *__.CreateAppointReq) (*__.CreateAppointResp, error) {
	//参数校验
	if in.UserId == 0 || in.MerchantId == 0 || in.Phone == "" || in.Address == "" || in.Num == 0 || in.Date == "" {
		return nil, fmt.Errorf("预约参数不能为空")
	}

	//校验商家Id
	var merchant model.Merchant
	err := config.DB.First(&merchant, in.MerchantId).Error
	if err != nil {
		return nil, fmt.Errorf("商家id不存在")
	}

	//校验用户Id
	var user model.User
	err = config.DB.First(&user, in.UserId).Error
	if err != nil {
		return nil, fmt.Errorf("用户id不存在")
	}
	//预约成功后生成取货码
	code := rand.Intn(9000) + 1000
	appoint := model.Appoint{
		MerchantId: uint(in.MerchantId),
		UserId:     uint(in.UserId),
		Date:       in.Date,
		Address:    in.Address,
		Num:        int(in.Num),
		Phone:      in.Phone,
		Code:       code,
	}
	config.DB.Create(&appoint)
	//预约成功后实现预约提醒功能
	reminder := model.Reminder{
		AppointId: appoint.ID,
		Address:   appoint.Address,
		Date:      appoint.Date,
		Num:       appoint.Num,
	}
	config.DB.Create(&reminder)
	return &__.CreateAppointResp{
		AppointId: int64(appoint.ID),
	}, nil
}

// MerchantAppoint 商家预约管理功能
func (s *Server) MerchantAppoint(_ context.Context, in *__.MerchantAppointReq) (*__.MerchantAppointResp, error) {
	//分页参数
	offest := (in.Page - 1) * in.Size
	//校验商家Id
	var merchant model.Merchant
	err := config.DB.First(&merchant, in.MerchantId).Error
	if err != nil {
		return nil, fmt.Errorf("商家id不存在")
	}
	//查询数据库
	var appoints []model.Appoint
	err = config.DB.Offset(int(offest)).Limit(int(in.Size)).Where("merchant_id=?", in.MerchantId).Find(&appoints).Error
	if err != nil {
		return nil, fmt.Errorf("查询数据库失败")
	}
	//转换格式
	var appointList []*__.AppointInto
	for _, o := range appoints {
		appointList = append(appointList, &__.AppointInto{
			AppointId:  uint64(o.ID),
			MerchantId: uint64(o.MerchantId),
			UserId:     uint64(o.UserId),
			Date:       o.Date,
			Address:    o.Address,
			Num:        int64(o.Num),
			Phone:      o.Phone,
		})
	}
	return &__.MerchantAppointResp{
		List: appointList,
	}, nil
}

// UserDelAppoint 预约码核销功能
func (s *Server) UserDelAppoint(_ context.Context, in *__.UserDelAppointReq) (*__.UserDelAppointResp, error) {

	//校验用户Id
	var user model.User
	err := config.DB.First(&user, in.UserId).Error
	if err != nil {
		return nil, fmt.Errorf("用户id不存在")
	}

	//查询数据库
	var appoint model.Appoint
	config.DB.Where("user_id=?", in.UserId).Delete(&appoint)

	return &__.UserDelAppointResp{
		Success: true,
		Message: "预约码核销成功",
	}, nil
}

// ContentAdd 门店评价功能
func (s *Server) ContentAdd(_ context.Context, in *__.ContentAddReq) (*__.ContentAddResp, error) {
	//参数校验
	if in.UserId == 0 || in.MerchantId == 0 || in.Comment == "" {
		return nil, fmt.Errorf("评价参数不能为空")
	}
	//校验商家Id
	var merchant model.Merchant
	err := config.DB.First(&merchant, in.MerchantId).Error
	if err != nil {
		return nil, fmt.Errorf("商家id不存在")
	}

	//校验用户Id
	var user model.User
	err = config.DB.First(&user, in.UserId).Error
	if err != nil {
		return nil, fmt.Errorf("用户id不存在")
	}
	content := model.Content{
		UserId:     uint(in.UserId),
		MerchantId: uint(in.MerchantId),
		Comment:    in.Comment,
	}
	config.DB.Create(&content)
	return &__.ContentAddResp{
		ContentId: int64(content.ID),
	}, nil
}

// MerchantContent 商家评价查看
func (s *Server) MerchantContent(_ context.Context, in *__.MerchantContentReq) (*__.MerchantContentResp, error) {
	//分页参数
	offest := (in.Page - 1) * in.Size
	//校验商家Id
	var merchant model.Merchant
	err := config.DB.First(&merchant, in.MerchantId).Error
	if err != nil {
		return nil, fmt.Errorf("商家id不存在")
	}
	//查询数据库
	var contents []model.Content
	err = config.DB.Offset(int(offest)).Limit(int(in.Size)).Where("merchant_id=?", in.MerchantId).Find(&contents).Error
	if err != nil {
		return nil, fmt.Errorf("查询数据库失败")
	}
	//转换格式
	var contentList []*__.ContentInto
	for _, o := range contents {
		contentList = append(contentList, &__.ContentInto{
			ContentId:  uint64(o.ID),
			UserId:     uint64(o.UserId),
			MerchantId: uint64(o.MerchantId),
			Comment:    o.Comment,
		})
	}
	return &__.MerchantContentResp{
		List: contentList,
	}, nil
}

// ShopList 商品展示功能
func (s *Server) ShopList(_ context.Context, in *__.ShopListReq) (*__.ShopListResp, error) {
	//分页参数
	offest := (in.Page - 1) * in.Size
	//查询数据库
	var shops []model.Shop
	db := config.DB.Offset(int(offest)).Limit(int(in.Size))
	//按“销量”排序
	if in.Num == 0 {
		db = db.Order("num desc")
	}
	if in.Num == 1 {
		db = db.Order("num asc")
	}

	db.Find(&shops)

	//转换格式
	var shopList []*__.ShopInto
	for _, o := range shops {
		shopList = append(shopList, &__.ShopInto{
			ShopId: int64(o.ID),
			Name:   o.Name,
			Price:  float32(o.Price),
			Num:    int64(o.Num),
		})
	}
	return &__.ShopListResp{
		List: shopList,
	}, nil
}

// PointList 查看自提点
func (s *Server) PointList(_ context.Context, in *__.PointListReq) (*__.PointListResp, error) {
	//分页参数
	offest := (in.Page - 1) * in.Size
	//查询数据库
	var points []model.Point
	db := config.DB.Offset(int(offest)).Limit(int(in.Size))
	db.Find(&points)

	//转换格式
	var pointList []*__.PointInto
	for _, o := range points {
		pointList = append(pointList, &__.PointInto{
			PointId: uint64(o.ID),
			Name:    o.Name,
			Address: o.Address,
			Date:    o.Date,
		})
	}
	return &__.PointListResp{
		List: pointList,
	}, nil
}
